package com.ukefu.webim.util.weixin.config;

import com.ukefu.core.UKDataContext;
import com.ukefu.util.UKTools;
import com.ukefu.webim.service.cache.CacheHelper;
import com.ukefu.webim.service.repository.InstructionRepository;
import com.ukefu.webim.service.repository.SNSAccountRepository;
import com.ukefu.webim.util.weixin.handler.MsgHandler;
import com.ukefu.webim.util.weixin.handler.SubscribeHandler;
import com.ukefu.webim.util.weixin.handler.UnsubscribeHandler;
import com.ukefu.webim.web.model.Instruction;
import com.ukefu.webim.web.model.SNSAccount;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class WechatMpConfiguration {

	private Logger logger = LoggerFactory.getLogger(getClass());

	private static WechatMpConfiguration configuration = new WechatMpConfiguration() ;
	
	public static WechatMpConfiguration getInstance(){
		return configuration ;
	}
	private Map<String , WeiXinConfiguration> multiRouterMap = new HashMap<String , WeiXinConfiguration>() ;
	
	public WeiXinConfiguration getConfiguration(String snsid){
		return multiRouterMap.get(snsid) ;
	}
	
	public void initSNSAccount(SNSAccountRepository snsAccountRes , InstructionRepository insRes){
		List<SNSAccount> snsAccountList = snsAccountRes.findBySnstype(UKDataContext.ChannelTypeEnum.WEIXIN.toString()) ;
		for(SNSAccount snsAccount : snsAccountList) {
			createRouter(snsAccount);
			/**
			 * 初始化 IMR指令
			 */
			List<Instruction> imrList = insRes.findBySnsidAndOrgi(snsAccount.getSnsid() , snsAccount.getOrgi()) ;
			for(Instruction ins : imrList){
				CacheHelper.getIMRCacheBean().put(ins.getTopic(), ins, ins.getOrgi());
			}
		}
	}
	/**
	 * 动态添加 微信公众号
	 * @param snsAccount
	 * @return
	 */
	public WeiXinConfiguration createRouter(SNSAccount snsAccount){
		
		WeiXinConfiguration configure = new WeiXinConfiguration() ;
		configure.setSnsid(snsAccount.getSnsid());
		configure.setConfigStorage(configStorage(snsAccount));
		configure.setService(wxMpService(configure.getConfigStorage()));
		configure.setRouter(router(configure.getService()));
		configure.setSnsAccount(snsAccount);

		multiRouterMap.put(snsAccount.getSnsid(),configure) ;
		return configure;
	}

    private WxMpConfigStorage configStorage(SNSAccount snsAccount) {
        WxMpInMemoryConfigStorage configStorage = new WxMpInMemoryConfigStorage();
        configStorage.setAppId(snsAccount.getAppkey());
        try {
        	if(StringUtils.isNotBlank(snsAccount.getSecret())){
				configStorage.setSecret(UKTools.decryption(snsAccount.getSecret()));
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
        configStorage.setToken(snsAccount.getToken());
        configStorage.setAesKey(snsAccount.getAeskey());

		configStorage.setAccessToken(snsAccount.getAuthaccesstoken());

        return configStorage;
    }

    private WxMpService wxMpService(WxMpConfigStorage configStorage) {
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(configStorage);
        return wxMpService;
    }

    private WxMpMessageRouter router(WxMpService wxMpService) {
        final WxMpMessageRouter router = new WxMpMessageRouter(wxMpService);
        
        router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SUBSCRIBE).handler(UKDataContext.getContext().getBean(SubscribeHandler.class)).end() ;
        router.rule().msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.UNSUBSCRIBE).handler(UKDataContext.getContext().getBean(UnsubscribeHandler.class)).end() ;
        router.rule().async(false).handler(UKDataContext.getContext().getBean(MsgHandler.class)).end() ;
        
        return router;
    }

}
